package com.test.storage;

import java.io.*;
import java.util.Properties;

/**
 * @author: zouren
 * @date: 2022/3/14
 * @description:
 */
public class FileSecretStorage implements SecretStorage {
    private String fileName;
    private Properties properties;
    protected boolean loaded;
    private String folder;
    private boolean skipEncryption = false;

    public FileSecretStorage() {
        this.fileName = "storage.dat";
        this.loaded = false;
        this.folder = ".licence";
    }

    @Override
    public void setSkipEncryption(boolean skipEncryption) {
        this.skipEncryption = skipEncryption;
    }

    @Override
    public boolean isSkipEncryption() {
        return this.skipEncryption;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }



    public String getFolder() {
        return folder;
    }

    public void setFolder(String folder) {
        this.folder = folder;
    }

    protected boolean isLoaded() {
        return this.loaded;
    }

    protected Properties getProperties() {
        if (!this.isLoaded()) {
            this.load();
        }

        if (!this.isLoaded()) {
            this.properties = new Properties();
            this.setLoaded(true);
        }

        return this.properties;
    }

    protected void setLoaded(boolean aLoaded) {
        this.loaded = aLoaded;
    }

    @Override
    public String getProperty(String key) {
        Properties delegate = this.getProperties();
        return delegate.getProperty(key);
    }

    @Override
    public String getProperty(String key, String defaultValue) {
        Properties delegate = this.getProperties();
        return delegate.getProperty(key, defaultValue);
    }

    @Override
    public Object setProperty(String key, String value) {
        Properties delegate = this.getProperties();

        return delegate.setProperty(key, value);
    }

    @Override
    public void load() {
        InputStream inputStream = this.getInputStream();
        if (inputStream != null) {
            try {
                try {
                    if (this.properties == null) {
                        this.properties = new Properties();
                    }
                    this.properties.clear();
                    this.properties.load(inputStream);
                    this.setLoaded(true);
                } finally {
                    inputStream.close();
                }
            } catch (IOException var6) {
                var6.printStackTrace();
            }
        }
    }

    @Override
    public void save() {
        OutputStream outputStream = this.getOutputStream();
        if (outputStream != null) {
            try {
                try {
                    this.properties.store(outputStream, (String) null);
                } finally {
                    outputStream.close();
                }
            } catch (IOException var6) {
                var6.printStackTrace();
            }
        }
    }

    public File getFile() {
        File storageFile;

        String userHome = System.getProperties().getProperty("user.home");
        storageFile = new File(this.folder != null ? new File(userHome, this.folder) : new File(userHome), this.fileName);


        return storageFile;
    }

    protected InputStream getInputStream() {
        InputStream result = null;

        try {
            File file = this.getFile();
            if (file.canRead()) {
                result = new FileInputStream(file);
                if (!this.isSkipEncryption()) {
                    result = new FileSecretStorage.DecodeInputStream(result);
                }
            }
        } catch (FileNotFoundException var3) {
            var3.printStackTrace();
        }

        return  result;
    }

    protected OutputStream getOutputStream() {
        OutputStream result = null;

        try {
            File file = this.getFile();
            if (!file.exists() || file.canWrite()) {
                file.getParentFile().mkdirs();
                result = new FileOutputStream(file);
                if (!this.isSkipEncryption()) {
                    result = new FileSecretStorage.EncodeOutputStream(result);
                }
            }
        } catch (FileNotFoundException var3) {
            var3.printStackTrace();
        }

        return  result;
    }

    protected static class DecodeInputStream extends FilterInputStream {
        protected int decode(int b) {
            return b ^ 18;
        }

        public DecodeInputStream(InputStream anInputStream) {
            super(anInputStream);
        }

        @Override
        public int read() throws IOException {
            return this.decode(super.read());
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            int bytesRead = super.read(b, off, len);
            if (bytesRead != -1) {
                for (int i = off; i < bytesRead; ++i) {
                    b[i] = (byte) this.decode(b[i]);
                }
            }

            return bytesRead;
        }
    }

    protected static class EncodeOutputStream extends FilterOutputStream {
        protected int encode(int b) {
            return b ^ 18;
        }

        public EncodeOutputStream(OutputStream anOutputStream) {
            super(anOutputStream);
        }

        public OutputStream getOutputStream() {
            return this.out;
        }

        @Override
        public void write(int b) throws IOException {
            super.write(this.encode(b));
        }
    }
}
